#include "parser.h"
#include "regex/stack.h"
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "vm.h"

tiny_token *make_token(enum tiny_token_type type, int offset)
{
    tiny_token *tmp = (tiny_token *)malloc(sizeof(tiny_token));
    tmp->next = NULL;
    tmp->lineno = 0;
    tmp->offset = offset;
    tmp->length = 0;
    tmp->type = type;
    return tmp;
}

tiny_token *tiny_parse(char *code, int length)
{
    int i = 0;
    tiny_token *root = NULL;
    tiny_token *tmp = NULL;
    for (i = 0; i < length; ++i)
    {
        //printf("=>%c\n",code[i]);
        switch (code[i])
        {
        case '"':
            //string
            if (root == NULL)
            {
                root = make_token(tiny_t_string, i);
                tmp = root;
            }
            else
            {
                tmp->next = make_token(tiny_t_string, i);
                tmp = tmp->next;
            }
            ++i;
            while (i < length && code[i] != '"')
            {
                if (code[i] == '\\')
                {
                    ++i;
                }
                ++i;
            }
            tmp->length = i - tmp->offset + 1;
            break;
        case '\'':
            if (root == NULL)
            {
                root = make_token(tiny_t_char, i);
                tmp = root;
            }
            else
            {
                tmp->next = make_token(tiny_t_char, i);
                tmp = tmp->next;
            }
            ++i;
            while (i < length && code[i] != '\'')
            {
                if (code[i] == '\\')
                {
                    ++i;
                }
                ++i;
            }
            tmp->length = i - tmp->offset + 1;
            break;
        case '(':
            if (root == NULL)
            {
                root = make_token(tiny_t_lp, i);
                tmp = root;
            }
            else
            {
                tmp->next = make_token(tiny_t_lp, i);
                tmp = tmp->next;
            }
            break;
        case ')':
            if (root == NULL)
            {
                root = make_token(tiny_t_rp, i);
                tmp = root;
            }
            else
            {
                tmp->next = make_token(tiny_t_rp, i);
                tmp = tmp->next;
            }
            break;
        case '[':
            //printf("=>%c\n",code[i]);
            if (root == NULL)
            {
                root = make_token(tiny_t_lp, i);
                tmp = root;
            }
            else
            {
                //printf("=>%p\n",tmp);

                tmp->next = make_token(tiny_t_lp, i);
                //printf("=>%p\n",tmp->next);
                tmp = tmp->next;
            }
            break;
        case ']':
            if (root == NULL)
            {
                root = make_token(tiny_t_rp, i);
                tmp = root;
            }
            else
            {
                tmp->next = make_token(tiny_t_rp, i);
                tmp = tmp->next;
            }
            break;
        default:
            if (isdigit(code[i]))
            {
                if (root == NULL)
                {
                    root = make_token(tiny_t_integer, i);
                    tmp = root;
                }
                else
                {
                    tmp->next = make_token(tiny_t_integer, i);
                    tmp = tmp->next;
                }
                while (i < length && isxdigit(code[i]))
                {
                    ++i;
                }
                tmp->length = i - tmp->offset;
                --i;
            }
            else if (code[i] != '(' && code[i] != '[' && code[i] != ')' && code[i] != ']' && !isspace(code[i]))
            {
                if (root == NULL)
                {
                    root = make_token(tiny_t_identify, i);
                    tmp = root;
                }
                else
                {
                    tmp->next = make_token(tiny_t_identify, i);
                    tmp = tmp->next;
                }
                while (i < length && (code[i] != '(' && code[i] != '[' && code[i] != ')' && code[i] != ']' && !isspace(code[i])))
                {
                    //printf("=>%c\n",code[i]);

                    ++i;
                }
                tmp->length = i - tmp->offset;
                --i;
            }

            break;
        }
    }
    return root;
}

void display_tokens(tiny_token *root)
{
    if (root == NULL)
    {
        return;
    }
    //printf("<%p>\n",root);
    switch (root->type)
    {
    case tiny_t_identify:
        printf("<identify>\n");
        break;
    case tiny_t_rp:
        printf("<rp>\n");
        break;
    case tiny_t_lp:
        printf("<lp>\n");
        break;
    case tiny_t_integer:
        printf("<integer>\n");
        break;
    case tiny_t_string:
        printf("<string>\n");
        break;
    case tiny_t_double:
        printf("<double>\n");
        break;
    }
    display_tokens(root->next);
}

tiny_value *tiny_compile(char *code, int length)
{
    tiny_token *tokens = tiny_parse(code, length);
    //display_tokens(tokens);
    //return NULL;
    Stack *stack = initStack();
    tiny_value *value = NULL;
    tiny_value *tmp = NULL;
    char *val = NULL;
    int i = 0;
    int n = 0;
    int len = 0;

    if (tokens == NULL)
    {
        return NULL;
    }
    while (tokens != NULL)
    {
        switch (tokens->type)
        {
        case tiny_t_lp:
            push(stack, NULL);
            break;
        case tiny_t_rp:
            value = NULL;
            len = 0;
            while (stackSize(stack) > 0)
            {
                tmp = (tiny_value *)pop(stack);
                if (tmp == NULL)
                {
                    break;
                }
                if (value != NULL)
                {
                    tmp->tail = value;
                }
                value = tmp;
                ++len;
            }
            //value == NULL error
            tmp = make_value(tiny_type_list);
            tmp->value.list = value;
            //printf("=length=> %d",len);
            tmp->length = len;
            push(stack, tmp);
            break;
        case tiny_t_integer:
            value = make_value(tiny_type_integer);
            val = (char *)malloc(tokens->length + 1);
            memset(val, 0, tokens->length + 1);
            memcpy(val, code + tokens->offset, tokens->length);
            value->value.int_ = atoi(val);
            //printf("%p==>integer:%d\n",value,value->value.int_);
            free(val);
            push(stack, value);
            break;
        case tiny_t_double:
            value = make_value(tiny_type_double);
            val = (char *)malloc(tokens->length + 1);
            memset(val, 0, tokens->length + 1);
            memcpy(val, code + tokens->offset, tokens->length);
            value->value.double_ = atof(val);
            free(val);
            push(stack, value);
            break;
        case tiny_t_char:
            value = make_value(tiny_type_char);
            val = (char *)malloc(tokens->length + 1);
            memset(val, 0, tokens->length + 1);
            value->value.char_ = atof(val);
            if (code[tokens->offset + 1] == '\\')
            {
                switch (code[tokens->offset + 2])
                {
                case 'f':
                    value->value.char_ = '\f';
                    break;
                case 'n':
                    value->value.char_ = '\n';
                    break;
                case 'r':
                    value->value.char_ = '\r';
                    break;
                case 't':
                    value->value.char_ = '\t';
                    break;
                case 'v':
                    value->value.char_ = '\v';
                    break;
                case '\\':
                    value->value.char_ = '\\';
                    break;
                case '\'':
                    value->value.char_ = '\'';
                    break;
                default:
                    //error
                    break;
                }
            }
            else
            {
                value->value.char_ = code[tokens->offset + 1];
            }
            push(stack, value);
            break;
        case tiny_t_string:
            value = make_value(tiny_type_string);
            val = (char *)malloc(tokens->length + 1);
            memset(val, 0, tokens->length + 1);
            //memcpy(val, code + tokens->offset, tokens->length);
            for (i = 1, n = 0; i < tokens->length - 1; ++i, ++n)
            {
                if (code[tokens->offset + i] == '\\')
                {
                    ++i;
                    switch (code[tokens->offset + i])
                    {
                    case 'f':
                        val[n] = '\f';
                        break;
                    case 'n':
                        val[n] = '\n';
                        break;
                    case 'r':
                        val[n] = '\r';
                        break;
                    case 't':
                        val[n] = '\t';
                        break;
                    case 'v':
                        val[n] = '\v';
                        break;
                    case '\\':
                        val[n] = '\\';
                        break;
                    case '"':
                        val[n] = '"';
                        break;
                    default:
                        //error
                        break;
                    }
                }
                else
                {
                    val[n] = code[tokens->offset + i];
                }
            }
            value->value.str = val;
            value->length = n;
            push(stack, value);
            break;
        case tiny_t_identify:
            if(*(code + tokens->offset)=='#' && tokens->length==2 && 
                (*(code + tokens->offset+1)=='t' || *(code + tokens->offset+1)=='f')){
                value = make_value(tiny_type_bool);
                if(*(code + tokens->offset+1)=='t'){
                    value->value.bool_ = 1;
                }else{
                    value->value.bool_ = 0;
                }
            }else{
                value = make_value(tiny_type_symbol);
                val = (char *)malloc(tokens->length + 1);
                memset(val, 0, tokens->length + 1);
                memcpy(val, code + tokens->offset, tokens->length);
                value->value.str = val;
            }
            
            push(stack, value);
            break;
        }
        tokens = tokens->next;
    }
    if (stackSize(stack) == 0)
    {
        return NULL;
    }
    if (stackSize(stack) == 1)
    {
        return (tiny_value *)pop(stack);
    }
    value = NULL;
    len = 0;
    while (stackSize(stack) > 0)
    {
        tmp = (tiny_value *)pop(stack);
        if (value != NULL)
        {
            tmp->tail = value;
        }
        value = tmp;
        ++len;
    }
    tmp = make_value(tiny_type_list);
    tmp->value.list = make_value(tiny_type_symbol);
    val = (char *)malloc(6);
    memset(val, 0, 6);
    memcpy(val, "begin", 5);
    tmp->value.list->value.str = val;
    tmp->value.list->tail = value;
    tmp->length = len + 1;
    releaseStack(stack);
    return tmp;
}

void trans_let_to_lambda(tiny_value *value)
{
    /**
    (let [(x 1)] (...))
    ((lambda [x] (...)) 1)
     */
    tiny_value *tmp = NULL;
    tiny_value *args = NULL;
    tiny_value *content = NULL;
    tiny_value *args1 = NULL;
    tiny_value *args2 = NULL;
    tiny_value *args3 = NULL;
    int i = 0;

    if (is_list(value))
    {
        if (is_symbol(value->value.list) && strcmp("let", value->value.list->value.str) == 0)
        {
            tmp = make_value(tiny_type_list);
            tmp->value.list = make_value(tiny_type_symbol);
            tmp->value.list->value.str = (char *)malloc(7);
            memset(tmp->value.list->value.str, 0, 7);
            memcpy(tmp->value.list->value.str, "lambda", 6);
            args = value->value.list->tail;
            content = args->tail;
            tmp->value.list->tail = args;
            tmp->length = 3;
            value->value.list = tmp;

            i = list_length(args);
            args1 = args->value.list;
            while (i > 0)
            {
                if (args2 == NULL)
                {
                    args2 = args1->value.list;
                    args3 = args2->tail;
                    args2->tail = NULL;
                    args->value.list = args2;
                    tmp->tail = args3;
                }
                else
                {
                    args2->tail = args1->value.list;
                    args2 = args2->tail;
                    args3->tail = args2->tail;
                    args2->tail = NULL;
                    args3 = args3->tail;
                }
                args1 = args1->tail;
                --i;
            }

            value->length = list_length(args) + 1;
        }
        else
        {
            tmp = value->value.list;
            while (tmp != NULL)
            {
                trans_let_to_lambda(tmp);
                tmp = tmp->tail;
            }
        }
    }
}

tiny_bytecode *_tiny_compile_secd(tiny_value *ast, tiny_env *env, int othercall,int *rescur)
{
    if (ast == NULL)
    {
        return NULL;
    }
    tiny_value *tmp = NULL;
    tiny_bytecode *bytecode = NULL;
    tiny_bytecode *cur = NULL;
    tiny_env *subenv = NULL;
    tiny_bytecode *ret_tmp = NULL;
    int n = 0;
    switch (ast->type)
    {
    case tiny_type_symbol:
        n = 0;
        tmp = NULL;
        //printf("===>%d\n",(int)findFromHash(env->symbol_table, ast->value.str));
        while (env != NULL)
        {
            tmp = (tiny_value *)findFromHash(env->symbol_table, ast->value.str);
            if (tmp != NULL)
            {
                cur  = make_bytecode(i_ld);
                cur->level = n;
                cur->pos = (int)tmp - 1;
                break;
            }
            ++n;
            env = env->up_level;
        }
        if (tmp == NULL)
        {
            cur  = make_bytecode(i_ldn);
            cur->op = ast  ;
        }
        break;
    case tiny_type_string:
    case tiny_type_char:
    case tiny_type_double:
    case tiny_type_integer:
        cur = make_bytecode(i_ldc);
        cur->op = ast;
        break;
    case tiny_type_nil:
        //printf("NIL\n");
        cur = make_bytecode(i_nil);
        break;
    case tiny_type_list:
        if (list_length(ast) > 0)
        {
            if (is_list(ast->value.list))
            {
                //printf("NIL\n");
                cur = make_bytecode(i_nil);
                bytecode = cur;
                tmp = ast->value.list->tail;
                while (tmp != NULL)
                {
                    cur->next = _tiny_compile_secd(tmp, env, othercall,rescur);
                    tmp = tmp->tail;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    //cur = cur->next;
                    cur->next = make_bytecode(i_cons);
                    cur = cur->next;
                    //printf("CONS\n");
                }
                cur->next = _tiny_compile_secd(ast->value.list, env, othercall,rescur);
                //printf("AP\n");
                while (cur->next != NULL)
                {
                    cur = cur->next;
                }
                //cur = cur->next;
                cur->next = make_bytecode(i_ap);
                cur = bytecode;
            }
            else
            {
                if (strcmp("lambda", ast->value.list->value.str) == 0)
                {
                    cur = make_bytecode(i_ldf);
                    bytecode = cur;
                    tmp = ast->value.list->tail->value.list;
                    subenv = make_env(env);
                    n = 1;
                    while (tmp != NULL)
                    {
                        set_env(subenv, tmp->value.str, (void *)n);
                        ++n;
                        tmp = tmp->tail;
                    }
                    //cur = bytecode;

                    bytecode->branch1 = _tiny_compile_secd(ast->value.list->tail->tail, subenv, 0,rescur);
                    ret_tmp = bytecode->branch1;
                    while (ret_tmp->next != NULL)
                    {
                        ret_tmp = ret_tmp->next;
                    }
                    ret_tmp->next = make_bytecode(i_rtn);
                    if(*rescur==1){
                        ret_tmp = make_bytecode(i_dum);
                        ret_tmp->next = make_bytecode(i_nil);
                        ret_tmp->next->next = bytecode;
                        bytecode->next  = make_bytecode(i_cons);
                        bytecode->next->next = make_bytecode(i_ldf);
                        bytecode->next->next->branch1 = make_bytecode(i_ld);
                        bytecode->next->next->branch1->level = 0;
                        bytecode->next->next->branch1->pos = 0;
                        bytecode->next->next->branch1->next = make_bytecode(i_rtn);
                        bytecode->next->next->next = make_bytecode(i_rap);
                        cur = ret_tmp;
                    }else{
                        cur = bytecode;
                    }
                    *rescur =0;
                }
                else if (strcmp("begin", ast->value.list->value.str) == 0)
                {
                    tmp = ast->value.list->tail;
                    bytecode = NULL;
                    while (tmp != NULL)
                    {
                        
                        if (cur == NULL)
                        {
                            if(tmp->next != NULL){
                                cur = _tiny_compile_secd(tmp, env, 1,rescur);
                            }else{
                                cur = _tiny_compile_secd(tmp, env, othercall,rescur);
                            }
                        }
                        else
                        {
                            if(tmp->next != NULL){
                                cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                            }else{
                                cur->next = _tiny_compile_secd(tmp, env, othercall,rescur);
                            }
                            
                        }

                        tmp = tmp->tail;
                        if (bytecode == NULL)
                        {
                            bytecode = cur;
                        }
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        //cur =cur->next;
                    }
                    cur = bytecode;
                }
                else if (strcmp("if", ast->value.list->value.str) == 0)
                {
                    cur = _tiny_compile_secd(ast->value.list->tail, env, othercall,rescur);
                    bytecode = cur;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_sel);
                    cur->next->branch1 = _tiny_compile_secd(ast->value.list->tail->tail, env, othercall,rescur);
                    ret_tmp = cur->next->branch1;
                    while (ret_tmp->next != NULL)
                    {
                        ret_tmp = ret_tmp->next;
                    }
                    ret_tmp->next = make_bytecode(i_join);
                    cur->next->branch2 = _tiny_compile_secd(ast->value.list->tail->tail->tail, env, othercall,rescur);
                    ret_tmp = cur->next->branch2;
                    while (ret_tmp->next != NULL)
                    {
                        ret_tmp = ret_tmp->next;
                    }
                    ret_tmp->next = make_bytecode(i_join);
                    cur = bytecode;
                }
                else if (strcmp("define", ast->value.list->value.str) == 0)
                {
                    cur = make_bytecode(i_ldc);
                    bytecode = cur;
                    cur->op = ast->value.list->tail;
                    cur->next = _tiny_compile_secd(ast->value.list->tail->tail, env, othercall,rescur);
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_def);
                    cur = bytecode;
                }
                else if (strcmp("recur", ast->value.list->value.str) == 0)
                {
                    cur = make_bytecode(i_nil);
                    bytecode = cur;
                    tmp = ast->value.list->tail;
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_cons);
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_ld);
                    cur->next->level = 1;
                    cur->next->pos = 0;
                    if(othercall==1){
                        cur->next->next = make_bytecode(i_ap);
                    }else{
                        cur->next->next = make_bytecode(i_dap);
                    }
                    cur=bytecode;
                    *rescur = 1;
                }
                else if (strcmp("quote", ast->value.list->value.str) == 0)
                {
                    cur = make_bytecode(i_ldc);
                    bytecode = cur;
                    cur->op = ast->value.list->tail;
                }
                else if (strcmp("=", ast->value.list->value.str) == 0)
                {
                    cur = _tiny_compile_secd(ast->value.list->tail, env, 1,rescur);
                    bytecode = cur;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = _tiny_compile_secd(ast->value.list->tail->tail, env, 1,rescur);
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_eq);
                     cur=bytecode;
                }
                else if (strcmp(">", ast->value.list->value.str) == 0)
                {
                    cur = _tiny_compile_secd(ast->value.list->tail, env, 1,rescur);
                    bytecode = cur;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = _tiny_compile_secd(ast->value.list->tail->tail, env, 1,rescur);
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_gt);
                     cur=bytecode;
                }
                else if (strcmp("<", ast->value.list->value.str) == 0)
                {
                    cur = _tiny_compile_secd(ast->value.list->tail, env, 1,rescur);
                    bytecode = cur;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = _tiny_compile_secd(ast->value.list->tail->tail, env, 1,rescur);
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_lt);
                     cur=bytecode;
                }
                else if (strcmp(">=", ast->value.list->value.str) == 0)
                {
                    cur = _tiny_compile_secd(ast->value.list->tail, env, 1,rescur);
                    bytecode = cur;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = _tiny_compile_secd(ast->value.list->tail->tail, env, 1,rescur);
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_ge);
                     cur=bytecode;
                }
                else if (strcmp("<=", ast->value.list->value.str) == 0)
                {
                    cur = _tiny_compile_secd(ast->value.list->tail, env, 1,rescur);
                    bytecode = cur;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = _tiny_compile_secd(ast->value.list->tail->tail, env, 1,rescur);
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_le);
                     cur=bytecode;
                }
                else if (strcmp("+", ast->value.list->value.str) == 0)
                {
                    tmp = ast->value.list->tail;
                    cur  = _tiny_compile_secd(tmp, env, 1,rescur);
                    bytecode = cur;
                    tmp = tmp->tail;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_add);
                        cur = cur->next;
                    }
                    //cur->next = make_bytecode(i_add);
                    cur = bytecode;
                }
                else if (strcmp("-", ast->value.list->value.str) == 0)
                {
                    tmp = ast->value.list->tail;
                    cur  = _tiny_compile_secd(tmp, env, 1,rescur);
                    bytecode = cur;
                    tmp = tmp->tail;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_sub);
                        cur = cur->next;
                    }
                    //cur->next = make_bytecode(i_add);
                    cur = bytecode;
                }
                else if (strcmp("*", ast->value.list->value.str) == 0)
                {
                    tmp = ast->value.list->tail;
                    cur  = _tiny_compile_secd(tmp, env, 1,rescur);
                    bytecode = cur;
                    tmp = tmp->tail;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_mul);
                        cur = cur->next;
                    }
                    //cur->next = make_bytecode(i_add);
                    cur = bytecode;
                }
                else if (strcmp("/", ast->value.list->value.str) == 0)
                {
                    tmp = ast->value.list->tail;
                    cur  = _tiny_compile_secd(tmp, env, 1,rescur);
                    bytecode = cur;
                    tmp = tmp->tail;
                    while (cur->next != NULL)
                    {
                        cur = cur->next;
                    }
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_div);
                        cur = cur->next;
                    }
                    //cur->next = make_bytecode(i_add);
                    cur = bytecode;
                }
                else if (strcmp("%", ast->value.list->value.str) == 0)
                {
                    cur = make_bytecode(i_nil);
                    bytecode = cur;
                    tmp = ast->value.list->tail;
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_cons);
                        cur = cur->next;
                    }
                    cur->next = make_bytecode(i_mod);
                    cur = bytecode;
                }
                else
                {
                    cur = make_bytecode(i_nil);
                    bytecode = cur;
                    tmp = ast->value.list->tail;
                    while (tmp != NULL)
                    {
                        cur->next = _tiny_compile_secd(tmp, env, 1,rescur);
                        tmp = tmp->tail;
                        while (cur->next != NULL)
                        {
                            cur = cur->next;
                        }
                        cur->next = make_bytecode(i_cons);
                        cur = cur->next;
                    }
                    n = 0;
                    tmp = NULL;
                    while (env != NULL)
                    {
                        tmp = (tiny_value *)findFromHash(env->symbol_table, ast->value.list->value.str);
                        if (tmp != NULL)
                        {
                            cur->next = make_bytecode(i_ld);
                            cur->next->level = n;
                            cur->next->pos = (int)tmp - 1;
                            break;
                        }
                        ++n;
                        env = env->up_level;
                    }
                    if (tmp == NULL)
                    {
                        //cur->next = make_bytecode(i_ldc);
                        //cur->next->op = ast->value.list;
                        //cur = cur->next;
                        cur->next = make_bytecode(i_ldfn);
                        cur->next->op = ast->value.list;
                        cur = cur->next;
                    }

                    if (othercall == 1)
                    {
                        cur->next = make_bytecode(i_ap);
                    }
                    else
                    {
                        cur->next = make_bytecode(i_tap);
                    }
                    cur = bytecode;
                }
            }
        }
        else
        {
        }
        break;
    }

    return cur;
}

tiny_bytecode *tiny_compile_secd(tiny_value *ast)
{
    if (ast == NULL)
    {
        return NULL;
    }
    tiny_bytecode *ret = NULL;
    tiny_bytecode *ret_tmp = NULL;
    tiny_env *env = make_env(NULL);
    int recur=0;
    ret = _tiny_compile_secd(ast, env, 1,&recur);
    ret_tmp = ret;
    while (ret_tmp->next != NULL)
    {
        ret_tmp = ret_tmp->next;
    }
    ret_tmp->next = make_bytecode(i_stop);
    return ret;
}